#!/usr/bin/python

import os, sys
import xml.etree.cElementTree as ET
from functions import *
from Cheetah.Template import Template
from urllib import quote_plus
from glob import glob
import traceback
import re
from xml.sax.saxutils import escape
import codecs
from xml.sax.saxutils import quoteattr

# optimizations
try:
    import psyco
    psyco.full()
except:
    print "No runtime optimization."
    pass

# templates
DEFAULT_OUTPUT="output.turtle"
TEMPLATE_DIR="templates"

templates = {}
for t in ["packages.csv", "package-dependencies.csv", "package-files.csv"]:
    extraction_home = os.environ.get("MPHS_PKG_EXTRACTION")
    template = extraction_home+'/templates/' + t
    templates[t] = open(template).read()

def get_template(file_name):
    extraction_home = os.environ.get("MPHS_PKG_EXTRACTION")
    path = extraction_home + '/templates/' + file_name
    tmpl = Template(file=path, filter='EncodeUnicode')
    return tmpl


class File:
    def __init__(self, path, type, size):
        self.path = path
        self.type = type
        self.size = size
       


def parse_package_metadata(file, packages_out, package_files_out, package_dependencies_out):
    """Parses package metadata files and outputs valid turtle format"""
    data = codecs.open( file, "r").read()

    try:
        res = ET.fromstring(data)
    except SyntaxError:
        # looks like we found an invalid character
        print >>sys.stderr, "Invalid characters found, stripping. %s\n" % file,
        logfile = os.environ.get("MPHS_LOG")+'/package-extraction.log'
        log_package("Invalid characters found, stripping. %s\n" % file, logfile)
        
        # this is slow, but it is the best we can do right now..
        #for match in regex.finditer(data):
        #    data = data[:match.start()] + "?" + data[match.end():]
        #res = ET.fromstring(data)
        return
    
    for package in res:
        params = {}
        # process package parameters
        # XPATH
        params["filename"] = package.get("filename")
        params["name"] = package.findtext("./name")
        params["license"] = package.findtext("./license")
        params["url"] = package.findtext("./homepage")
       	params["description"] = package.findtext("./description").replace("\"","\\\"")
        
        template = 'packages.csv'
        info = get_template(template)
        info.name = params["name"]
        scripts = package.find("./scripts")
        info.filename = params["filename"]
        info.prein = scripts.findtext("./prein").replace("\"","\\\"")
        info.postin = scripts.findtext("./postin").replace("\"","\\\"")
        info.preun = scripts.findtext("./preun").replace("\"","\\\"")
        info.postun = scripts.findtext("./postun").replace("\"","\\\"")
        info.distrib = package.findtext("./distribution")
        info.version = package.findtext("./version")
        info.release = package.findtext("./release")
        info.branch = package.findtext("./branch")
        info.section = package.findtext("./section")
        info.architecture = package.findtext("./arch")
        if (params["filename"].endswith('src.rpm'))
            info.architecture='SRPMS'
        info.group = package.findtext("./group")
        info.sourcerpm = package.findtext("./sourcerpm")
        info.buildhost = package.findtext("./buildhost")
        info.buildtime = package.findtext("./buildtime")
        info.size = package.findtext("./size")
        info.packager = package.findtext("./packager")
        info.summary = package.findtext("./summary").replace("\"","\\\"")
        info.description = params["description"]
        info.license = params["license"]
        info.home = params["url"]
        info.size = package.findtext("./size")
        
        print >>packages_out, str(info)
        
        info = get_template('package-dependencies.csv')
        info.filename = params["filename"]
        info.distrib = package.findtext("./distribution")
        for provide in package.findall("./provides"):
           info.item = provide.text
           info.dep = "provides"
           print >>package_dependencies_out, str(info)
        
        for require in package.findall("./requires"):
            info.item = require.text
            info.dep = "requires"
            print >>package_dependencies_out, str(info)        
        
        info = get_template('package-files.csv')

        info.files = []
        info.filename = params["filename"]
        info.distrib = package.findtext("./distribution")
        for file in package.findall("./file"):
            info.path= file.get("path")
            info.type = file.get("type")
            info.size = file.get("size")
            info.extra = file.get("extra")
            if info.extra == None:
                info.extra = 0
            print >>package_files_out, str(info)

if __name__ == "__main__":
    if len(sys.argv) < 3:
        print "Usage: %s <package-metadata-directory> <output-dir> [<package-list-filter-file-path>]" % sys.argv[0]
        sys.exit(1)
    package_dir = sys.argv[1]
    output_dir = sys.argv[2]
    packages_out = open(os.path.join(output_dir+"/","packages.csv"), "w")
    package_files_out = open(os.path.join(output_dir+"/","package-files.csv"), "w")
    package_dependencies_out = open(os.path.join(output_dir+"/","package-dependencies.csv"), "w")

    # looking for files
    metadata_files = []
    if (len(sys.argv) == 4):
        # keep only the packages that were added recently
        added_packages_file = sys.argv[3]
        added_packages_list = read_as_string(added_packages_file)
        added_packages = added_packages_list.split()
        for added_package in added_packages:
            dir_path = os.path.join(package_dir,added_package)
            try:
                for file in os.listdir(dir_path):
                   if (file == 'metadata.xml'):
                         metadata_files.append(os.path.join(dir_path, file))
            except:
                print >>sys.stderr, "not found: %s" % dir_path
    else:            
        for dirs in os.listdir(package_dir):
            dir_path = os.path.join(package_dir,dirs)
            if os.path.isdir(dir_path):
                for metadata_file in os.listdir(dir_path):
                    if (metadata_file == 'metadata.xml'):
                        metadata_files.append(os.path.join(dir_path, metadata_file))
                        print >>sys.stderr, "Metadata file %s.." % os.path.join(dir_path, metadata_file)
                    
    for file in metadata_files:
        try:
            parse_package_metadata(file, packages_out, package_files_out, package_dependencies_out )
#           os.unlink(file)
        except:
            traceback.print_exc()
            print >>sys.stderr, "error parsing %s: %s" % (file, sys.exc_value)
            sys.exit(1)

#    print files

